package com.css.zfzx.fxpg.modules.casulaty.probability.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.alibaba.fastjson.JSONObject;
import com.css.bpm.platform.org.division.repository.entity.DivisionEntity;
import com.css.zfzx.fxpg.common.utils.BeanUtil;
import com.css.zfzx.fxpg.common.utils.EasyPoiExcelUtil;
import com.css.zfzx.fxpg.modules.buildings.data.repository.FxBuildingsNativeRepository;
import com.css.zfzx.fxpg.modules.buildings.data.repository.entity.FxBuildingsEntity;
import com.css.zfzx.fxpg.modules.buildings.data.viewobjects.FxBuildingsQueryParams;
import com.css.zfzx.fxpg.modules.casulaty.probability.repository.FxCasulatyProbabilityNativeRepository;
import com.css.zfzx.fxpg.modules.casulaty.probability.repository.FxCasulatyProbabilityRepository;
import com.css.zfzx.fxpg.modules.casulaty.probability.repository.entity.FxCasulatyProbabilityEntity;
import com.css.zfzx.fxpg.modules.casulaty.probability.service.FxCasulatyProbabilityService;
import com.css.zfzx.fxpg.modules.casulaty.probability.viewobjects.FxCasulatyProbabilityQueryParams;
import com.css.zfzx.fxpg.modules.casulaty.probability.viewobjects.FxCasulatyProbabilityVO;
import com.css.bpm.platform.api.local.PlatformAPI;
import com.css.bpm.platform.sys.dict.repository.entity.DictItemEntity;
import com.css.zfzx.fxpg.modules.casulaty.probability.viewobjects.FxCasulatyTProbabilityVO;
import com.css.zfzx.fxpg.modules.percent.casualty.repository.FxCasualtyPercentNativeRepository;
import com.css.zfzx.fxpg.modules.percent.casualty.repository.entity.FxCasualtyPercentEntity;
import com.css.zfzx.fxpg.modules.percent.casualty.viewobjects.FxCasualtyPercentQueryParams;
import com.css.zfzx.fxpg.modules.percent.daynight.repository.FxDayNightPercentNativeRepository;
import com.css.zfzx.fxpg.modules.percent.daynight.repository.entity.FxDayNightPercentEntity;
import com.css.zfzx.fxpg.modules.percent.daynight.viewobjects.FxDayNightPercentQueryParams;
import com.css.zfzx.fxpg.modules.vulnerability.danger.repository.FxVulnerabilityDangerNativeRepository;
import com.css.zfzx.fxpg.modules.vulnerability.danger.repository.entity.FxVulnerabilityDangerEntity;
import com.css.zfzx.fxpg.modules.vulnerability.danger.viewobjects.FxVulnerabilityDangerQueryParams;
import com.css.zfzx.fxpg.modules.vulnerability.province.repository.FxVulnerabilityProvinceNativeRepository;
import com.css.zfzx.fxpg.modules.vulnerability.province.repository.entity.FxVulnerabilityProvinceEntity;
import com.css.zfzx.fxpg.modules.vulnerability.province.viewobjects.FxVulnerabilityProvinceQueryParams;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import com.css.bpm.platform.utils.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

import static com.css.zfzx.fxpg.common.utils.BigRoot.bigRoot;

/**
 * @author leon
 * @date 2020-12-03
 */
@Service
@Slf4j
public class FxCasulatyProbabilityServiceImpl implements FxCasulatyProbabilityService {

    @Autowired
    private FxCasulatyProbabilityRepository fxCasulatyProbabilityRepository;
    @Autowired
    private FxCasulatyProbabilityNativeRepository fxCasulatyProbabilityNativeRepository;
    @Autowired
    private FxVulnerabilityDangerNativeRepository fxVulnerabilityDangerNativeRepository;
    @Autowired
    private FxVulnerabilityProvinceNativeRepository fxVulnerabilityProvinceNativeRepository;
    /**
     * 房屋数据Repository
     */
    @Autowired
    private FxBuildingsNativeRepository buildingsNativeRepository;
    /**
     * 伤亡率
     */
    @Autowired
    private FxCasualtyPercentNativeRepository casualtyPercentNativeRepository;
    /**
     * 昼夜
     */
    @Autowired
    private FxDayNightPercentNativeRepository dayNightPercentNativeRepository;

    @Override
    public JSONObject queryFxCasulatyProbabilitys(FxCasulatyProbabilityQueryParams queryParams, int curPage, int pageSize) {
        Page<FxCasulatyProbabilityEntity> fxCasulatyProbabilityPage = this.fxCasulatyProbabilityNativeRepository.queryFxCasulatyProbabilitys(queryParams, curPage, pageSize);
        JSONObject jsonObject = PlatformPageUtils.formatPageData(fxCasulatyProbabilityPage);
        return jsonObject;
    }

    @Override
    public List<FxCasulatyProbabilityEntity> listFxCasulatyProbabilitys(FxCasulatyProbabilityQueryParams queryParams) {
        return fxCasulatyProbabilityNativeRepository.listFxCasulatyProbabilitys(queryParams);
    }


    @Override
    public FxCasulatyProbabilityEntity getFxCasulatyProbability(String id) {
        FxCasulatyProbabilityEntity fxCasulatyProbability = this.fxCasulatyProbabilityRepository.findById(id).orElse(null);
        return fxCasulatyProbability;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FxCasulatyProbabilityEntity saveFxCasulatyProbability(FxCasulatyProbabilityEntity fxCasulatyProbability) {
        String uuid = UUIDGenerator.getUUID();
        fxCasulatyProbability.setId(uuid);
        fxCasulatyProbability.setCreateUser(PlatformSessionUtils.getUserId());
        fxCasulatyProbability.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
        this.fxCasulatyProbabilityRepository.save(fxCasulatyProbability);
        return fxCasulatyProbability;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FxCasulatyProbabilityEntity updateFxCasulatyProbability(FxCasulatyProbabilityEntity fxCasulatyProbability) {
        fxCasulatyProbability.setUpdateUser(PlatformSessionUtils.getUserId());
        fxCasulatyProbability.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
        String id = fxCasulatyProbability.getId();
        FxCasulatyProbabilityEntity one = fxCasulatyProbabilityRepository.findById(id).get();
        BeanUtil.copyPropertiesIgnoreNull(fxCasulatyProbability, one);
        this.fxCasulatyProbabilityRepository.save(one);
        return fxCasulatyProbability;
    }

    @Override
    public FxCasulatyProbabilityEntity updateXYByY(FxCasulatyProbabilityEntity fxCasulatyProbability) {
        FxCasulatyProbabilityEntity one = fxCasulatyProbabilityRepository.getOne(fxCasulatyProbability.getId());
        Float pOne = one.getProbabilityOne();
        Float pOne2 = fxCasulatyProbability.getProbabilityOne();
        if (pOne2 != null && !pOne2.equals(pOne)) {
            FxCasulatyProbabilityQueryParams queryParams = new FxCasulatyProbabilityQueryParams();
            // 省市区、人员伤亡、时间段、破坏程度
            BeanUtils.copyProperties(fxCasulatyProbability, queryParams);
            // 区划危险性数据信息
            FxVulnerabilityDangerEntity dangerEntity = fxVulnerabilityDangerNativeRepository.listFxVulnerabilityDangers(new FxVulnerabilityDangerQueryParams(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea())).get(0);
            // 结构类型
            List<DictItemEntity> structureTypes = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("structureType");
            // 破坏程度：1-4
            List<DictItemEntity> damageDegrees = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("damageDegree");

            // 房屋数据表：根据省市区获取房屋数据List
            List<FxBuildingsEntity> fxBuildingsEntities = listBuildings(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea());
            /**
             * 房屋根据用途分为三类：I II III
             * 第Ⅰ类：住宅、公寓、学生和职工集体宿舍、宾馆、招待所等人员居住场所；
             * 第Ⅱ类：办公室、生产车间、教室等工作与学习场所；
             * 第Ⅲ类为娱乐场所、体育馆、车站、候机室、码头等人员较集中的公共场所
             */
            HashMap<String, List<FxBuildingsEntity>> map = classifyByPurpose(fxBuildingsEntities);
            List<FxBuildingsEntity> I = map.get("I");
            List<FxBuildingsEntity> II = map.get("II");
            List<FxBuildingsEntity> III = map.get("III");
            /**
             * 三类各自不同结构类型的面积SI1-SI5,...SIII1-SIII5
             */
            HashMap<String, Float> map1 = countBuildingArea(I);
            HashMap<String, Float> map2 = countBuildingArea(II);
            HashMap<String, Float> map3 = countBuildingArea(III);
            // (具体某个区的)伤亡-重伤率
            HashMap<String, FxCasualtyPercentEntity> casualtyMap = getCasualtyPercent(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea());

            /**
             * XMap
             * 砖混-重伤-白天-1
             */
            HashMap<String, Float> xMap = getXMap(map1, map2, map3, queryParams, casualtyMap, structureTypes);
            /**
             * YMap
             * 所有结构类型下不同破坏程度的y=易损性*危险性值
             */
            HashMap<String, Float> yMap = getYMap(structureTypes, queryParams, dangerEntity);

            String casulaty = queryParams.getCasulaty();
            String period = queryParams.getPeriod();

            // 人员伤亡：重伤、死亡
            String cas = casulaty;
            // 时间段：白天、夜间
            String per = period;
            HashMap<String, ArrayList<Double>> xyListMap = getXYMap(xMap, yMap, structureTypes, damageDegrees, cas, per);
            ArrayList<Double> k1List = new ArrayList<>();
            ArrayList<Double> k0List = new ArrayList<>();
            // 不同结构类型
            for (DictItemEntity structure : structureTypes) {
                String structureCode = structure.getDictItemCode();
                ArrayList<Double> xList = xyListMap.get(structureCode + "xList");
                ArrayList<Double> yList = xyListMap.get(structureCode + "yList");
                // xList和yList大小都是4
                /**
                 * 线性回归求k
                 */
                HashMap<String, Double> kMap = regressionK(xList, yList);
                double k0 = kMap.get("k0");
                if ("0.0".equals(Double.valueOf(k0))) {
                    k0 = 0.1d;
                }
                double k1 = kMap.get("k1");
                k0List.add(k0);
                k1List.add(k1);
            }
            // 给定4个y值：y1=10-2、y2=10-3、y3=10-5、y4=10-6，分别对应6中的4个方程式求出4组x值，
            // 分别为x1A...x1D;x2A...x2D;...x4A...x4D。
            // x = (k0/y)的开K1根号
            double y1 = Math.pow(10, -2);
            double y2 = Math.pow(10, -3);
            double y3 = Math.pow(10, -5);
            double y4 = Math.pow(10, -6);
            ArrayList<Double> ySum = new ArrayList<>();
            ySum.add(y1);
            ySum.add(y2);
            ySum.add(y3);
            ySum.add(y4);
            ArrayList<Double> xSum = new ArrayList<>();
            int scale = 8;
            for (int j = 0; j < 4; j++) {
                Double k0 = k0List.get(j);
                Double k1 = k1List.get(j);
                if ("0.0".equals(k1.toString())) {
                    k1 = 1.0;
                }
                if ("0.0".equals(k0.toString())) {
                    xSum.add(0d);
                } else {
                    BigDecimal num1 = new BigDecimal(k0 / y1);
                    BigDecimal num2 = new BigDecimal(k0 / y2);
                    BigDecimal num3 = new BigDecimal(k0 / y3);
                    BigDecimal num4 = new BigDecimal(k0 / y4);
                    int n = k1.intValue();
                    // 一个数的负次方即为这个数的正次方的倒数。
                    if (n < 0) {
                        n = -n;
                        num1 = new BigDecimal(y1 / k0);
                        num2 = new BigDecimal(y2 / k0);
                        num3 = new BigDecimal(y3 / k0);
                        num4 = new BigDecimal(y4 / k0);
                    }
                    double x1 = bigRoot(num1, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                    double x2 = bigRoot(num2, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                    double x3 = bigRoot(num3, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                    double x4 = bigRoot(num4, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                    double x = x1 + x2 + x3 + x4;
                    xSum.add(x);
                }
            }
            /**
             * 线性回归求K
             */
            HashMap<String, Double> KMap = regressionK(xSum, ySum);
            Double K0 = KMap.get("k0");
            Double K1 = KMap.get("k1");

            Double Y = fxCasulatyProbability.getProbabilityOne().doubleValue();
            BigDecimal num = new BigDecimal(K0 / Y);
            int n = K1.intValue();
            Double X = bigRoot(num, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
            fxCasulatyProbability.setCasualties(Float.parseFloat(X.toString()));
        }
        updateFxCasulatyProbability(fxCasulatyProbability);
        return fxCasulatyProbability;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteFxCasulatyProbabilitys(List<String> ids) {
        List<FxCasulatyProbabilityEntity> fxCasulatyProbabilityList = this.fxCasulatyProbabilityRepository.findAllById(ids);
        if (!PlatformObjectUtils.isEmpty(fxCasulatyProbabilityList) && fxCasulatyProbabilityList.size() > 0) {
            for (FxCasulatyProbabilityEntity fxCasulatyProbability : fxCasulatyProbabilityList) {
                this.fxCasulatyProbabilityRepository.delete(fxCasulatyProbability);
            }
        }
    }

    @Override
    public List<DictItemEntity> getValidDictItemsByDictCode(String dictCode) {
        List<DictItemEntity> validDictItems = PlatformAPI.getDictAPI().getValidDictItemsByDictCode(dictCode);
        return validDictItems;
    }

    @Override
    public String findByDictCodeAndDictItemCode(String dictCode, String dictItemCode) {
        DictItemEntity dictItem = PlatformAPI.getDictAPI().getValidDictItemByDictCodeAndDictItemCode(dictCode, dictItemCode);
        String dictItemName = "";
        if (PlatformObjectUtils.isNotEmpty(dictItem)) {
            dictItemName = dictItem.getDictItemName();
        }
        return dictItemName;
    }

    @Override
    public void initialize() {
        List<FxCasulatyProbabilityEntity> all = fxCasulatyProbabilityRepository.findAll();
        if (all != null && all.size() > 0) {
            throw new RuntimeException("请删除所有数据后进行初始化！");
        } else {
            List<DivisionEntity> provinceDivisions = PlatformAPI.getDivisionAPI().getSubDivisions("root");
            for (DivisionEntity provinceDivision : provinceDivisions) {
                // 省
                String province = provinceDivision.getDivisionName();
                // 直辖市
                if ("北京市".equals(province) || "天津市".equals(province) || "上海市".equals(province) || "重庆市".equals(province)) {
                    // 市
                    String city = province;
                    List<DivisionEntity> areaDivisions = PlatformAPI.getDivisionAPI().getSubDivisions(provinceDivision.getDivisionId());
                    for (DivisionEntity areaDivision : areaDivisions) {
                        FxCasulatyProbabilityEntity entity = new FxCasulatyProbabilityEntity();
                        // 区
                        String area = areaDivision.getDivisionName();
                        entity.setProvince(province);
                        entity.setCity(city);
                        entity.setArea(area);
                        // 类型字典值并且保存
                        saveInitialize(entity);
                        // 临时只添加一个区
                        break;
                    }
                }
                // 省下面的正常市
                else {
                    List<DivisionEntity> cityDivisions = PlatformAPI.getDivisionAPI().getSubDivisions(provinceDivision.getDivisionId());
                    for (DivisionEntity cityDivision : cityDivisions) {
                        // 市
                        String city = cityDivision.getDivisionName();
                        List<DivisionEntity> areaDivisions = PlatformAPI.getDivisionAPI().getSubDivisions(cityDivision.getDivisionId());
                        for (DivisionEntity areaDivision : areaDivisions) {
                            // 区
                            String area = areaDivision.getDivisionName();
                            FxCasulatyProbabilityEntity entity = new FxCasulatyProbabilityEntity();
                            entity.setProvince(province);
                            entity.setCity(city);
                            entity.setArea(area);
                            // 类型字典值并且保存
                            saveInitialize(entity);
                        }
                    }
                }
                // 临时添加数据，只添加北京的；正式时候去掉break
                break;
            }
        }
    }

    private void saveInitialize(FxCasulatyProbabilityEntity entity) {
        String[] casulaties = "重伤、死亡".split("、");
        // 人员伤亡
        for (String casulaty : casulaties) {
            entity.setCasulaty(casulaty);
            String[] periods = "白天、夜间".split("、");
            // 时间段
            for (String period : periods) {
                entity.setPeriod(period);
                // 破坏程度
                List<DictItemEntity> damageDegrees = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("damageDegree");
                for (int i = 1; i < damageDegrees.size(); i++) {
                    String damageDegreeName = damageDegrees.get(i).getDictItemCode();
                    entity.setDamageDegree(damageDegreeName);
                    this.saveFxCasulatyProbability(entity);
                }
            }
        }
    }

    @Override
    public String exportExcel(FxCasulatyProbabilityQueryParams queryParams, HttpServletResponse response) {
        try {
            List<FxCasulatyProbabilityEntity> entities = fxCasulatyProbabilityNativeRepository.listFxCasulatyProbabilitys(queryParams);
            // 深拷贝
            ArrayList<FxCasulatyProbabilityVO> vos = new ArrayList<>();
            for (FxCasulatyProbabilityEntity entity : entities) {
                FxCasulatyProbabilityVO vo = new FxCasulatyProbabilityVO();
                BeanUtils.copyProperties(entity, vo);
                vos.add(vo);
            }
            // 导出
            EasyPoiExcelUtil.exportExcel(vos, "人员伤亡概率计算", "人员伤亡概率计算", FxCasulatyProbabilityVO.class, "人员伤亡概率计算.xlsx", response);
            return "导出成功";
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @Override
    public String exportTExcel(FxCasulatyProbabilityQueryParams queryParams, HttpServletResponse response) {
        try {
            double T = Double.parseDouble(queryParams.getYearSpan());
            List<FxCasulatyProbabilityEntity> entities = fxCasulatyProbabilityNativeRepository.listFxCasulatyProbabilitys(queryParams);
            // 深拷贝
            ArrayList<FxCasulatyTProbabilityVO> vos = new ArrayList<>();
            for (int i = 0; i < entities.size(); i++) {
                Double val = (1 - Math.pow((1 - entities.get(i).getProbabilityTwo()), T));
                val = getPrecision(val, 4);
                int span = (i / 4) * 4;
                double t_probabilityTwo = 0;
                double changedExpect = 0;
                for (int j = 0; j < 4; j++) {
                    t_probabilityTwo = 1 - Math.pow((1 - entities.get(span + j).getProbabilityTwo()), T);
                    t_probabilityTwo = getPrecision(t_probabilityTwo, 4);
                    changedExpect += t_probabilityTwo * (entities.get(span + j).getCasualties());
                }
                changedExpect = getPrecision(changedExpect, 4);
                FxCasulatyTProbabilityVO vo = new FxCasulatyTProbabilityVO();
                BeanUtils.copyProperties(entities.get(i), vo);
                vo.setProbabilityTwo(Float.parseFloat(Double.toString(val)));
                // 人数四舍五入取整：Math.round()
                vo.setChangedExpect(Float.parseFloat(Long.toString(Math.round(changedExpect))));
                vos.add(vo);
            }
            // 导出
            EasyPoiExcelUtil.exportExcel(vos, "T年的伤亡估计", "T年的伤亡估计", FxCasulatyTProbabilityVO.class, "T年的伤亡估计.xlsx", response);
            return "导出成功";
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @Override
    public String importExcel(MultipartFile file) {
        try {
            // 返回的消息
            StringBuilder returnMsg = new StringBuilder();
            // 导入的参数信息
            ImportParams params = new ImportParams();
            // 设置解析从第1+1+1行开始
            params.setTitleRows(1);
            params.setHeadRows(1);
            // 是否需要校验
            params.setNeedVerify(true);
            // 获取到Excel数据
            ExcelImportResult<FxCasulatyProbabilityVO> result = ExcelImportUtil.importExcelMore(file.getInputStream(), FxCasulatyProbabilityVO.class, params);
            List<FxCasulatyProbabilityVO> list = result.getList();
            // 批量新增
            this.saveExcel(list);
            returnMsg.append("成功导入" + result.getList().size() + "条，失败" + result.getFailList().size() + "条<br/>");
            if (result.isVerifyFail()) {
                // 校验返回失败行信息
                Iterator<FxCasulatyProbabilityVO> iterator = result.getFailList().iterator();
                while (iterator.hasNext()) {
                    FxCasulatyProbabilityVO vo = iterator.next();
                    String error = "";
                    returnMsg.append("第" + vo.getRowNum() + "行" + vo.getErrorMsg() + "<br/>");
                    returnMsg.append(error);
                }
            }
            return returnMsg.toString();
        } catch (RuntimeException e) {
            log.error(e.getMessage(), e);
            return e.getMessage();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            if ("库中该数据最多一条，请管理员清理数据库冗余数据！".equals(e.getMessage())) {
                return e.getMessage();
            } else {
                return "导入失败，请检查数据正确性";
            }
        }
    }

    @Override
    public String importTExcel(MultipartFile file) {
        try {
            // 返回的消息
            StringBuilder returnMsg = new StringBuilder();
            // 导入的参数信息
            ImportParams params = new ImportParams();
            // 设置解析从第1+1+1行开始
            params.setTitleRows(1);
            params.setHeadRows(1);
            // 是否需要校验
            params.setNeedVerify(true);
            // 获取到Excel数据
            ExcelImportResult<FxCasulatyTProbabilityVO> result = ExcelImportUtil.importExcelMore(file.getInputStream(), FxCasulatyTProbabilityVO.class, params);
            List<FxCasulatyTProbabilityVO> list = result.getList();
            // 批量新增
            this.saveTExcel(list);
            returnMsg.append("成功导入" + result.getList().size() + "条，失败" + result.getFailList().size() + "条<br/>");
            if (result.isVerifyFail()) {
                // 校验返回失败行信息
                Iterator<FxCasulatyTProbabilityVO> iterator = result.getFailList().iterator();
                while (iterator.hasNext()) {
                    FxCasulatyTProbabilityVO vo = iterator.next();
                    String error = "";
                    returnMsg.append("第" + vo.getRowNum() + "行" + vo.getErrorMsg() + "<br/>");
                    returnMsg.append(error);
                }
            }
            return returnMsg.toString();
        } catch (RuntimeException e) {
            log.error(e.getMessage(), e);
            return e.getMessage();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            if ("库中该数据最多一条，请管理员清理数据库冗余数据！".equals(e.getMessage())) {
                return e.getMessage();
            } else {
                return "导入失败，请检查数据正确性";
            }
        }
    }

    @Transactional
    @Override
    public void updateExpect(FxCasulatyProbabilityEntity fxCasulatyProbability) {
        FxCasulatyProbabilityQueryParams queryParams = new FxCasulatyProbabilityQueryParams();
        // 省市区
        queryParams.setProvince(fxCasulatyProbability.getProvince());
        queryParams.setCity(fxCasulatyProbability.getCity());
        queryParams.setArea(fxCasulatyProbability.getArea());
        // 人员伤亡、时间段
        queryParams.setCasulaty(fxCasulatyProbability.getCasulaty());
        queryParams.setPeriod(fxCasulatyProbability.getPeriod());
        List<FxCasulatyProbabilityEntity> list = fxCasulatyProbabilityNativeRepository.listFxCasulatyProbabilitys(queryParams);

        float expect = 0;
        for (FxCasulatyProbabilityEntity entity : list) {
            float probabilityTwo = 0, casualties = 0;
            if (entity.getProbabilityTwo() != null && entity.getCasualties() != null) {
                probabilityTwo = entity.getProbabilityTwo();
                casualties = entity.getCasualties();
            }
            float v = probabilityTwo * casualties;
            expect += v;
        }
        if (Math.abs(expect) > .0001) {
            for (FxCasulatyProbabilityEntity entity : list) {
                entity.setExpect(expect);
                updateFxCasulatyProbability(entity);
            }
        }
    }


    private void saveTExcel(List<FxCasulatyTProbabilityVO> list) {
        for (int i = 0; i < list.size(); i++) {
            FxCasulatyProbabilityEntity entity = new FxCasulatyProbabilityEntity();
            FxCasulatyTProbabilityVO vo = list.get(i);
            // 将VO数据映射拷贝到库表中
            BeanUtils.copyProperties(vo, entity);
            saveOrUpdate(entity);
        }
    }

    private void saveExcel(List<FxCasulatyProbabilityVO> list) {
        for (int i = 0; i < list.size(); i++) {
            FxCasulatyProbabilityEntity entity = new FxCasulatyProbabilityEntity();
            FxCasulatyProbabilityVO vo = list.get(i);
            FxCasulatyTProbabilityVO tVo = new FxCasulatyTProbabilityVO();
            // 线上计算值导入时不读取值入库
            BeanUtils.copyProperties(vo, tVo);
            // 将VO数据映射拷贝到库表中
            BeanUtils.copyProperties(tVo, entity);
            saveOrUpdate(entity);
        }
    }

    /**
     * 保存或者修改
     *
     * @param entity
     */
    private void saveOrUpdate(FxCasulatyProbabilityEntity entity) {
        FxCasulatyProbabilityQueryParams queryParams = new FxCasulatyProbabilityQueryParams();
        // 省市区
        queryParams.setProvince(entity.getProvince());
        queryParams.setCity(entity.getCity());
        queryParams.setArea(entity.getArea());
        // 人员伤亡、时间段、破坏程度
        queryParams.setCasulaty(entity.getCasulaty());
        queryParams.setPeriod(entity.getPeriod());
        queryParams.setDamageDegree(entity.getDamageDegree());
        // 查询库数据
        List<FxCasulatyProbabilityEntity> entities = fxCasulatyProbabilityNativeRepository.listFxCasulatyProbabilitys(queryParams);
        // 若查到数据为空，则新增
        if (CollectionUtils.isEmpty(entities)) {
            this.saveFxCasulatyProbability(entity);
        } else {
            if (entities.size() == 1) {
                FxCasulatyProbabilityEntity sourceEntity = entities.get(0);
                BeanUtil.copyPropertiesIgnoreNull(entity, sourceEntity);
                this.updateFxCasulatyProbability(sourceEntity);
            } else {
                throw new RuntimeException("库中该数据最多一条，请管理员清理数据库冗余数据！");
            }
        }
    }

    @Override
    public String calculate(FxCasulatyProbabilityQueryParams queryParams) {
        try {
            // 区划危险性数据信息
            List<FxVulnerabilityDangerEntity> dangerEntities = fxVulnerabilityDangerNativeRepository.listFxVulnerabilityDangers(new FxVulnerabilityDangerQueryParams(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea()));
            if (CollectionUtils.isEmpty(dangerEntities)) {
                return "风险结果数据为空！";
            }
            FxVulnerabilityDangerEntity dangerEntity = dangerEntities.get(0);
            if (dangerEntity == null || dangerEntity.getViEarthquakeIntensity() == null) {
                return "该区对应的危险性烈度概率为空，请去'风险评估数据管理-区划危险性数据管理'添加数据！";
            }
            // 结构类型
            List<DictItemEntity> structureTypes = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("structureType");
            // 破坏程度：1-4
            List<DictItemEntity> damageDegrees = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("damageDegree");

            // 房屋数据表：根据省市区获取房屋数据List
            List<FxBuildingsEntity> fxBuildingsEntities = listBuildings(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea());
            if (CollectionUtils.isEmpty(fxBuildingsEntities)) {
                return "该区房屋数据为空，请去'风险评估数据管理-房屋数据管理'添加数据！";
            }

            /**
             * 房屋根据用途分为三类：I II III
             * 第Ⅰ类：住宅、公寓、学生和职工集体宿舍、宾馆、招待所等人员居住场所；
             * 第Ⅱ类：办公室、生产车间、教室等工作与学习场所；
             * 第Ⅲ类为娱乐场所、体育馆、车站、候机室、码头等人员较集中的公共场所
             */
            HashMap<String, List<FxBuildingsEntity>> map = classifyByPurpose(fxBuildingsEntities);
            List<FxBuildingsEntity> I = map.get("I");
            List<FxBuildingsEntity> II = map.get("II");
            List<FxBuildingsEntity> III = map.get("III");
            /**
             * 三类各自不同结构类型的面积SI1-SI5,...SIII1-SIII5
             */
            HashMap<String, Float> map1 = countBuildingArea(I);
            HashMap<String, Float> map2 = countBuildingArea(II);
            HashMap<String, Float> map3 = countBuildingArea(III);
            // (具体某个区的)伤亡-重伤率
            HashMap<String, FxCasualtyPercentEntity> casualtyMap = getCasualtyPercent(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea());

            /**
             * XMap
             * 砖混-重伤-白天-1
             */
            HashMap<String, Float> xMap = getXMap(map1, map2, map3, queryParams, casualtyMap, structureTypes);
            /**
             * YMap
             * 所有结构类型下不同破坏程度的y=易损性*危险性值
             */
            HashMap<String, Float> yMap = getYMap(structureTypes, queryParams, dangerEntity);

            String casulaty = queryParams.getCasulaty();
            String period = queryParams.getPeriod();

            ArrayList<String> casulaties = new ArrayList<>();
            ArrayList<String> periods = new ArrayList<>();
            // 一个区所有的计算值(16个)
            if (StringUtils.isEmpty(casulaty) && StringUtils.isEmpty(period)) {
                casulaties.add("重伤");
                casulaties.add("死亡");
                periods.add("白天");
                periods.add("夜间");
            } else if (StringUtils.isEmpty(casulaty) && StringUtils.isNotEmpty(period)) {
                // 人员伤亡为空， 时间段不为空
                casulaties.add("重伤");
                casulaties.add("死亡");
                periods.add(period);
            } else {
                // 人员伤亡不为空， 时间段为空
                casulaties.add(casulaty);
                periods.add("白天");
                periods.add("夜间");
            }
            // 人员伤亡：重伤、死亡
            for (int i = 0; i < casulaties.size(); i++) {
                String cas = casulaties.get(i);
                // 时间段：白天、夜间
                for (String per : periods) {
                    HashMap<String, ArrayList<Double>> xyListMap = getXYMap(xMap, yMap, structureTypes, damageDegrees, cas, per);
                    ArrayList<Double> k1List = new ArrayList<>();
                    ArrayList<Double> k0List = new ArrayList<>();
                    // 不同结构类型
                    for (DictItemEntity structure : structureTypes) {
                        String structureCode = structure.getDictItemCode();
                        ArrayList<Double> xList = xyListMap.get(structureCode + "xList");
                        ArrayList<Double> yList = xyListMap.get(structureCode + "yList");
                        // xList和yList大小都是4
                        /**
                         * 线性回归求k
                         */
                        HashMap<String, Double> kMap = regressionK(xList, yList);
                        double k0 = kMap.get("k0");
                        if ("0.0".equals(Double.valueOf(k0))) {
                            k0 = 0.1d;
                        }
                        double k1 = kMap.get("k1");
                        k0List.add(k0);
                        k1List.add(k1);
                    }
                    // 给定4个y值：y1=10-2、y2=10-3、y3=10-5、y4=10-6，分别对应6中的4个方程式求出4组x值，
                    // 分别为x1A...x1D;x2A...x2D;...x4A...x4D。
                    // x = (k0/y)的开K1根号
                    double y1 = Math.pow(10, -2);
                    double y2 = Math.pow(10, -3);
                    double y3 = Math.pow(10, -5);
                    double y4 = Math.pow(10, -6);
                    ArrayList<Double> ySum = new ArrayList<>();
                    ySum.add(y1);
                    ySum.add(y2);
                    ySum.add(y3);
                    ySum.add(y4);
                    ArrayList<Double> xSum = new ArrayList<>();
                    int scale = 8;
                    for (int j = 0; j < 4; j++) {
                        Double k0 = k0List.get(j);
                        Double k1 = k1List.get(j);
                        // 若k1为0.0时，给一个默认值
                        if ("0.0".equals(k1.toString())) {
                            k1 = 1.0;
                        }
                        // 若k0为0.0时,xSum添加为0
                        if ("0.0".equals(k0.toString())) {
                            xSum.add(0d);
                        } else {
                            BigDecimal num1 = new BigDecimal(k0 / y1);
                            BigDecimal num2 = new BigDecimal(k0 / y2);
                            BigDecimal num3 = new BigDecimal(k0 / y3);
                            BigDecimal num4 = new BigDecimal(k0 / y4);
                            int n = k1.intValue();
                            // 一个数的负次方即为这个数的正次方的倒数。
                            if (n < 0) {
                                n = -n;
                                num1 = new BigDecimal(y1 / k0);
                                num2 = new BigDecimal(y2 / k0);
                                num3 = new BigDecimal(y3 / k0);
                                num4 = new BigDecimal(y4 / k0);
                            }
                            double x1 = bigRoot(num1, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                            double x2 = bigRoot(num2, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                            double x3 = bigRoot(num3, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                            double x4 = bigRoot(num4, n, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
                            double x = x1 + x2 + x3 + x4;
                            xSum.add(x);
                        }
                    }
                    /**
                     * 线性回归求K
                     */
                    HashMap<String, Double> KMap = regressionK(xSum, ySum);
                    Double K0 = KMap.get("k0");
                    Double K1 = KMap.get("k1");
                    Double a = KMap.get("a");
                    Double b = KMap.get("b");

                    /**
                     * 线性回归方法
                     */
                    Double[] xlist = new Double[xSum.size()];
                    Double[] ylist = new Double[ySum.size()];
                    xSum.toArray(xlist);
                    ySum.toArray(ylist);

                    // 根据省市区(必须)、人员伤亡、时间段查询伤亡概率表，4条
                    FxCasulatyProbabilityQueryParams params = new FxCasulatyProbabilityQueryParams();
                    BeanUtils.copyProperties(queryParams, params);
                    params.setCasulaty(cas);
                    params.setPeriod(per);
                    List<FxCasulatyProbabilityEntity> list = fxCasulatyProbabilityNativeRepository.listFxCasulatyProbabilitys(queryParams);
                    for (FxCasulatyProbabilityEntity entity : list) {
                        Float casualties = entity.getCasualties();
                        double casualtyToll;
                        // 若伤亡人树为空，则赋值一个随机数（或者抛出异常，告诉操作值此值不能为空）
                        if (casualties == null || StringUtils.isBlank(casualties.toString())) {
                            casualtyToll = Math.random() * 100;
                        } else {
                            casualtyToll = casualties.doubleValue();
                        }
                        int n = -K1.intValue();
                        if (K0.intValue() == 0) {
                            K0 = 0.1;
                        }
                        // ko * casualtyToll^n
                        Double one = K0 * Math.pow(casualtyToll, n);
                        // 若值为NAN则赋值为0
                        if (one.isNaN()) {
                            one = 0.0;
                        } else if (one.toString().contains("-")) {
                            String ex = one.toString().split("-")[1];
                            int ex2 = Integer.parseInt(ex) - 2;
                            one = one * Math.pow(10, ex2);
                        }
                        // 判断one是否是Infinite
                        if (one.isInfinite()) {
                            entity.setProbabilityOne(0.0f);
                        } else {
                            entity.setProbabilityOne(Float.parseFloat(one.toString()));
                        }
                        updateFxCasulatyProbability(entity);
                    }
                }
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
            return e.getMessage();
        }
        return "计算成功！";
    }

    /**
     * y = ax+b
     * lny = lnK0-k1x
     *
     * @param xList
     * @param yList
     * @return
     */
    private HashMap<String, Double> regressionK(List<Double> xList, List<Double> yList) {
        HashMap<String, Double> map = new HashMap<>();
        int n = xList.size() + 1;
        double sumXY = 0;
        double sumX = 0;
        double sumY = 0;
        double sumXX = 0;
        for (int i = 0; i < xList.size(); i++) {
            double x = xList.get(i);
            double y = yList.get(i);
            sumXY += x * y;
            sumX += x;
            sumY += y;
            sumXX += x * x;
        }
        double avgX = sumX / n;
        double avgY = sumY / n;
        double b = 0;
        if ((n * sumXY - sumX * sumX) != 0) {
            b = (n * sumXX - sumX * sumY) / (n * sumXX - sumX * sumX);
        }
        double a = avgY - b * avgX;

        double k1 = -a;
        double k0 = Math.pow(Math.E, b);
        map.put("a", a);
        map.put("b", b);
        map.put("k1", k1);
        map.put("k0", k0);
        return map;
    }


    private double getPrecision(double f, int newScale) {
        BigDecimal bg = new BigDecimal(f);
        /**
         * 参数：
         newScale - 要返回的 BigDecimal 值的标度。
         roundingMode - 要应用的舍入模式。
         返回：
         一个 BigDecimal，其标度为指定值，其非标度值可以通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定。
         */
        return bg.setScale(newScale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


    private HashMap<String, ArrayList<Double>> getXYMap(HashMap<String, Float> xMap, HashMap<String, Float> yMap,
                                                        List<DictItemEntity> structureTypes,
                                                        List<DictItemEntity> damageDegrees,
                                                        String cas, String per) {
        HashMap<String, ArrayList<Double>> xyListMap = new HashMap<>();
        // 不同结构类型
        for (DictItemEntity structure : structureTypes) {
            String structureCode = structure.getDictItemCode();
            ArrayList<Double> xList = new ArrayList<>();
            ArrayList<Double> yList = new ArrayList<>();
            // 轻微破坏->完全破坏
            for (int i = 1; i < damageDegrees.size(); i++) {
                String damageDegree = damageDegrees.get(i).getDictItemCode();
                // 砖混-重伤-白天-1
                Float x = xMap.get(structureCode + "-" + cas + "-" + per + "-" + damageDegree);

                xList.add(x.doubleValue());
                // 砖混-y1
                Float y = yMap.get(structureCode + "-y" + damageDegree);
                yList.add(y.doubleValue());
            }
            xyListMap.put(structureCode + "xList", xList);
            xyListMap.put(structureCode + "yList", yList);
        }
        return xyListMap;
    }

    private HashMap<String, Float> getXMap(HashMap<String, Float> map1, HashMap<String, Float> map2, HashMap<String, Float> map3, FxCasulatyProbabilityQueryParams queryParams, HashMap<String, FxCasualtyPercentEntity> casualtyMap, List<DictItemEntity> structureTypes) {
        // 人口密度
        Float η = 0.4f;
        ArrayList<String> periods = new ArrayList<>();
        ArrayList<String> casulaties = new ArrayList<>();
        // 请求参数：时间段和人员伤亡
        String paramsPeriod = queryParams.getPeriod();
        String paramsCasulaty = queryParams.getCasulaty();
        // 时间段：夜间、白天
        if (StringUtils.isEmpty(paramsPeriod)) {
            periods.add("夜间");
            periods.add("白天");
        } else {
            periods.add(paramsPeriod);
        }
        // 人员伤亡：重伤、死亡
        if (StringUtils.isEmpty(paramsCasulaty)) {
            casulaties.add("重伤");
            casulaties.add("死亡");
        } else {
            casulaties.add(paramsCasulaty);
        }

        // XMap
        HashMap<String, Float> xMap = new HashMap<>();
        for (String period : periods) {
            Float C1 = getC(period, "I类");
            Float C2 = getC(period, "II类");
            Float C3 = getC(period, "III类");
            Float SC;
            // 不同结构房屋下重伤人数（x值）
            for (int i = 0; i < structureTypes.size(); i++) {
                String key = "S" + (i + 1);
                SC = map1.get(key) * C1 + map2.get(key) * C2 + map3.get(key) * C3;
                String structureCode = structureTypes.get(i).getDictItemCode();
                for (String casulaty : casulaties) {
                    putXMap(SC, period, casulaty, structureCode, η, xMap, casualtyMap);
                }
            }
        }
        return xMap;
    }

    private void putXMap(Float SC, String period, String casulaty, String structureCode, Float η, HashMap<String, Float> xMap, HashMap<String, FxCasualtyPercentEntity> casualtyMap) {
        // 破坏程度:轻微破坏、中等破坏、严重破坏、完全破坏
        String[] damageDerees = "1、2、3、4".split("、");
        for (String damageDeree : damageDerees) {
            // 伤亡率
            Float percent;
            try {
                if ("重伤".equals(casulaty)) {
                    percent = Float.parseFloat(casualtyMap.get(damageDeree).getSeriousPrercent());
                } else {
                    // 死亡
                    percent = Float.parseFloat(casualtyMap.get(damageDeree).getDeathPrercent());
                }
            } catch (NullPointerException e) {
                e.printStackTrace();
                throw new NullPointerException("该区下面重伤或死亡百分比数据为空,请去'风险评估综合管理-模型参数管理-人员伤亡率'添加数据！");
            }
            Float x = SC * η * percent;
            // 砖混-重伤-白天-1 1:轻微破坏
            xMap.put(structureCode + "-" + casulaty + "-" + period + "-" + damageDeree, x);
        }
    }

    /**
     * 获取昼夜百分比
     *
     * @param period
     * @param houseType 房屋类别
     * @return
     */
    private Float getC(String period, String houseType) {
        // 室内人员昼夜在不同空间位置的百分比
        FxDayNightPercentEntity nightPercentIEntity = dayNightPercentNativeRepository.listFxDayNightPercents(new FxDayNightPercentQueryParams(houseType)).get(0);
        // 昼夜人员在室内百分比
        Float C = 0.0f;
        if ("夜间".equals(period)) {
            Float nightMax = Float.parseFloat(nightPercentIEntity.getNightMax());
            Float nightMin = Float.parseFloat(nightPercentIEntity.getNightMin());
            C = (nightMin + (nightMax - nightMin) / 2) / 100;
        } else {
            Float dayMax = Float.parseFloat(nightPercentIEntity.getDayMax());
            Float dayMin = Float.parseFloat(nightPercentIEntity.getDayMin());
            C = (dayMin + (dayMax - dayMin) / 2) / 100;
        }
        return C;
    }

    /**
     * 只获取重伤率
     *
     * @param province
     * @param city
     * @param area
     * @return
     */
    private HashMap<String, FxCasualtyPercentEntity> getCasualtyPercent(String province, String city, String area) {
        FxCasualtyPercentQueryParams queryParams = new FxCasualtyPercentQueryParams();
        queryParams.setProvince(province);
        queryParams.setCity(city);
        queryParams.setArea(area);
        // 破坏程度:轻微破坏、中等破坏、严重破坏、完全破坏
        String[] damageDerees = "1、2、3、4".split("、");
        HashMap<String, FxCasualtyPercentEntity> map = new HashMap<>();
        for (String damageDeree : damageDerees) {
            queryParams.setDamageDegree(damageDeree);
            // 库里应该是有且只有一条数据
            FxCasualtyPercentEntity percentEntitity = casualtyPercentNativeRepository.listFxCasualtyPercents(queryParams).get(0);
            map.put(damageDeree, percentEntitity);
        }
        return map;
    }

    private HashMap<String, Float> getYMap(List<DictItemEntity> structureTypes, FxCasulatyProbabilityQueryParams queryParams, FxVulnerabilityDangerEntity dangerEntity) {
        HashMap<String, Float> yMap = new HashMap<>();
        for (DictItemEntity structure : structureTypes) {
            String structureCode = structure.getDictItemCode();
            // 易损性QueryParams
            FxVulnerabilityProvinceQueryParams vulnerabilityQueryParams = new FxVulnerabilityProvinceQueryParams();
            // 省市区、结构类型，查出4条数据分别对应轻微破坏-完全破坏
            vulnerabilityQueryParams.setProvince(queryParams.getProvince());
            vulnerabilityQueryParams.setCity(queryParams.getCity());
            vulnerabilityQueryParams.setArea(queryParams.getArea());
            vulnerabilityQueryParams.setStructureType(structureCode);
            List<FxVulnerabilityProvinceEntity> vulnerabilityProvinceEntities = fxVulnerabilityProvinceNativeRepository.listFxVulnerabilityProvinces(vulnerabilityQueryParams);
            for (int i = 1; i < vulnerabilityProvinceEntities.size(); i++) {
                // 易损性值
                FxVulnerabilityProvinceEntity vuEntity = vulnerabilityProvinceEntities.get(i);
                Float vuVI = vuEntity.getVulnerabilityVI();
                Float vuVII = vuEntity.getVulnerabilityVII();
                Float vuVIII = vuEntity.getVulnerabilityVIII();
                Float vuIX = vuEntity.getVulnerabilityIX();
                Float vuX = vuEntity.getVulnerabilityX();
                // 危险性烈度概率
                Float viIntensity = dangerEntity.getViEarthquakeIntensity();
                Float viiIntensity = dangerEntity.getViiEarthquakeIntensity();
                Float viiiIntensity = dangerEntity.getViiiEarthquakeIntensity();
                Float ixIntensity = dangerEntity.getIxEarthquakeIntensity();
                Float xIntensity = dangerEntity.getXEarthquakeIntensity();
                try {
                    float y = vuVI * viIntensity + vuVII * viiIntensity + vuVIII * viiiIntensity + vuIX * ixIntensity + vuX * xIntensity;
                    // 砖混-y1 1:轻微破坏
                    yMap.put(structureCode + "-y" + i, y);
                } catch (NullPointerException e) {
                    e.printStackTrace();
                    throw new NullPointerException("该区对应的危险性烈度概率为空，请去'风险评估数据管理-区划危险性数据管理'添加数据！");
                }
            }
        }
        return yMap;
    }

    private HashMap<String, Float> countBuildingArea(List<FxBuildingsEntity> list) {
        HashMap<String, Float> map = new HashMap<>();
        // 结构类型
        String[] structureTypes = {"单层砖混", "2-3层砖混", "多层砖混", "钢混框架", "钢混框剪"};
        // 结构类型对应的面积
        float S1 = 0;
        float S2 = 0;
        float S3 = 0;
        float S4 = 0;
        float S5 = 0;
        for (FxBuildingsEntity entity : list) {
            float buildingArea = entity.getBuildingArea();
            String structureType = entity.getStructureType();
            if (StringUtils.isNotBlank(structureType)) {
                if (structureTypes[0].equals(structureType)) {
                    S1 += buildingArea;
                    continue;
                }
                if (structureTypes[1].equals(structureType)) {
                    S2 += buildingArea;
                    continue;
                }
                if (structureTypes[2].equals(structureType)) {
                    S3 += buildingArea;
                    continue;
                }
                if (structureTypes[3].equals(structureType)) {
                    S4 += buildingArea;
                    continue;
                }
                if (structureTypes[4].equals(structureType)) {
                    S5 += buildingArea;
                    continue;
                }
            }
        }
        map.put("S1", S1);
        map.put("S2", S2);
        map.put("S3", S3);
        map.put("S4", S4);
        map.put("S5", S5);
        return map;
    }


    private HashMap<String, List<FxBuildingsEntity>> classifyByPurpose(List<FxBuildingsEntity> fxBuildingsEntities) {
        HashMap<String, List<FxBuildingsEntity>> map = new HashMap<>();
        String I = "住宅、公寓、宿舍宿舍、宾馆、招待所、居住";
        String II = "办公室、生产车间、教室、工作、学习";
        String III = "娱乐场所、体育馆、车站、候机室、码头、公共";
        String[] purposeI = I.split("、");
        String[] purposeII = II.split("、");
        String[] purposeIII = III.split("、");
        ArrayList<FxBuildingsEntity> IBuildingsEntities = new ArrayList<>();
        ArrayList<FxBuildingsEntity> IIBuildingsEntities = new ArrayList<>();
        ArrayList<FxBuildingsEntity> IIIBuildingsEntities = new ArrayList<>();
        // 刷选三类
        for (FxBuildingsEntity entity : fxBuildingsEntities) {
            String purpose = entity.getPurpose();
            boolean flag = true;
            // 判断用途是否为第I类
            for (String s : purposeI) {
                if (purpose.contains(s)) {
                    IBuildingsEntities.add(entity);
                    flag = false;
                    break;
                }
            }
            // 判断用途是否为第II类
            if (flag) {
                for (String s : purposeII) {
                    if (purpose.contains(s)) {
                        IIBuildingsEntities.add(entity);
                        flag = false;
                        break;
                    }
                }
            }
            // 判断用途是否为第III类
            if (flag) {
                for (String s : purposeIII) {
                    if (purpose.contains(s)) {
                        IIIBuildingsEntities.add(entity);
                        flag = false;
                        break;
                    }
                }
            }
        }
        map.put("I", IBuildingsEntities);
        map.put("II", IIBuildingsEntities);
        map.put("III", IIIBuildingsEntities);
        return map;
    }

    private List<FxBuildingsEntity> listBuildings(String province, String city, String area) {
        FxBuildingsQueryParams queryParams = new FxBuildingsQueryParams();
        queryParams.setProvince(province);
        queryParams.setCity(city);
        queryParams.setArea(area);
        List<FxBuildingsEntity> buildingsEntities = buildingsNativeRepository.listFxBuildings(queryParams);
        return buildingsEntities;
    }
}
